<?php

namespace app\common\service\pay;


use Alipay\EasySDK\Kernel\Config;
use Alipay\EasySDK\Kernel\Factory;
use Alipay\EasySDK\Kernel\Util\ResponseChecker;
use app\common\service\ApiService;
use ba\Exception;

class AlipayService extends ApiService
{
    private function getOptions()
    {
        $appId = env('ALIPAY.ALIPAY_APPID') ?? '';
        if (empty($appId)) {
            getResponseException('请配置支付宝APPID', [], 1, 'ERROR');
        }
        $privateKey = env('ALIPAY.ALIPAY_PRIVATE_KEY') ?? '';
        if (empty($privateKey)) {
            getResponseException('请配置支付宝PRIVATE_KEY', [], 1, 'ERROR');
        }
        $publicKey = env('ALIPAY.ALIPAY_PUBLIC_KEY') ?? '';
        if (empty($publicKey)) {
            getResponseException('请配置支付宝PUBLIC_KEY', [], 1, 'ERROR');
        }
        $options = new Config();
        $options->protocol = 'https';
        $options->gatewayHost = 'openapi.alipay.com';
        $options->signType = 'RSA2';

        $options->appId = $appId;

        // 为避免私钥随源码泄露，推荐从文件中读取私钥字符串而不是写入源码中
        $options->merchantPrivateKey = $privateKey;
        $options->alipayPublicKey = $publicKey;
        return $options;
    }

    /**
     * 支付宝扫码支付
     */

    public function scanCodePay($orderNo, $totalAmount, $subject, $notifyUrl)
    {
        $error = compact('orderNo', 'totalAmount', 'subject', 'notifyUrl');
        //1. 设置参数（全局只需设置一次）
        Factory::setOptions($this->getOptions());
        $notifyUrl = request()->domain() . "/index.php" . $notifyUrl;
        try {
            //2. 发起API调用（以支付能力下的统一收单交易创建接口为例）
            $result = Factory::payment()->faceToFace()
                ->asyncNotify($notifyUrl)
                // ->batchOptional(['timeout_express' => $timeoutExpress])
                ->preCreate($subject, $orderNo, $totalAmount);
            $responseChecker = new ResponseChecker();
            //3. 处理响应或异常
            if ($responseChecker->success($result)) {
                return $result->qrCode;
            } else {
                $error['error'] = $result->msg . "，" . $result->subMsg;
                logSave($error, 'scanCodePay', 'wxPayService');
                getResponseException('支付错误,请检查异常', [], 1, 'ERROR');
            }
        } catch (Exception $e) {
            $error['error'] = $e->getMessage();
            logSave($error, 'scanCodePay', 'wxPayService');
            getResponseException('支付错误,请检查异常', [], 1, 'ERROR');
        }
    }

    public function payNotify($function)
    {
        $request = app()->request;
        $params = $request->filter('trim')->param();
        LogSave([
            'request' => json_encode($params, true),
            'message' => '支付宝支付回调通知'
        ], 'payNotify', 'alipayService');
        Factory::setOptions($this->getOptions());
        $verifiedStatus = Factory::payment()->common()->verifyNotify($params);
        $timestamp = time();
        $notifyTime = strtotime($params['notify_time']);
        $timeOffsetStatus = 300 >= abs($timestamp - (int)$notifyTime);
        if ($verifiedStatus && $timeOffsetStatus) {
            if ($params['trade_status'] != 'TRADE_SUCCESS') {
                logSave([
                    'request' => $params,
                    'message' => '支付失败'
                ], 'payNotify', 'wxPayService');
                return false;
            }
            return  $function([
                'out_trade_no' => $params['out_trade_no'],
                'total_price' => $params['total_amount'],
                'transaction_id' => $params['trade_no']
            ]);
        }

        return false;

    }

}
